home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / dev / debug / apurify_v1_1.lha / apurify / doc / APurify.doc.fre next >
Encoding:
Text File  |  1995-04-10  |  18.2 KB  |  363 lines

  1.                    APurify
  2.                    -------
  3.  
  4.               (c) par Samuel DEVULDER
  5.                  Avril 1995
  6.  
  7.                Samuel.Devulder@info.unicaen.fr
  8.  
  9. DESCRIPTION (COURTE):
  10. --------------------
  11.     APurify est un programme qui permet de detecter les acces  illegaux  en
  12.     memoire de vos  programmes    sans  utilisation  de  dispositif  materiel
  13.     exterieur (MMU). Il permet d'eviter un certain  nombre  de  bugs  du  a
  14.     l'acces a de la memoire non detenue par le programme.
  15.  
  16. SYNOPSIS:
  17. --------
  18.     APurify [-revinfo] <Fichier source> [<Fichier destination>]
  19.  
  20.     APurify -revinfo
  21.     Pour avoir les informations concernant APurify (le nom,  la  taille
  22.     et la date  des  modules  le  composant  ainsi    que  le  nombre  de
  23.     compilations deja effectuees).
  24.  
  25.     APurify <Fichier source> <Fichier destination>
  26.     Analyse le fichier source assembleur et genere une  version  de  ce
  27.     fichier source pret a etre assemblee puis reliee  a  APur.lib.    Les
  28.     acces memoire illegaux de ce fichier  source  seront  detectes    par
  29.     APurify. Le fichier destination  peut  etre  identique    au  fichier
  30.     source.
  31.  
  32.     APurify <Fichier source>
  33.     Idem que: APurify <Fichier source> <Fichier source>. ie: le fichier
  34.     apres purification (:-)) aura le meme nom que le fichier source.
  35.  
  36. DESCRIPTION (UN PEU PLUS LONGUE):
  37. --------------------------------
  38.     En regle generale, dans un programme au niveau du  microprocesseur,
  39.     il y a deux sorte d'acces a la memoire. Il y a les acces directs et les
  40.     acces indirects en memoire. Par exemple, en C, l'acces direct peut etre
  41.     assimile a l'acces des variables globales. L'acces indirect a l'acces a
  42.     une valeur d'un tableau. Plus precisement, l'acces direct correspond  a
  43.     la lecture ou l'ecriture dans une variable dont l'adresse est connue  a
  44.     la compilation ou des le chargement du programme  en  memoire.  L'acces
  45.     indirect est  utilise  pour  des  variables  dont  l'adresse  et  fixee
  46.     dynamiquement par le programme. Par exemple, si p est un  pointeur    sur
  47.     un tableau alloue par malloc(),  *p  est  un  acces  indirect.  L'acces
  48.     indirect se produit aussi dans le cas d'instructions de la  forme  T[i]
  49.     ou T est un tableau global. En effet, l'adresse memoire de  T[i]  n'est
  50.     pas connue par avance. Elle depend de la valeur de    l'indice  i.  C'est
  51.     pourquoi cet element requiert un acces indirect. On parle d'indirection
  52.     lorsqu'il s'agit d'acces indirect a la memoire.
  53.  
  54.     Un programme normal ne doit pas en regle general acceder  a  de  la
  55.     memoire qui ne lui appartient pas. Ce genre d'acces  a  de  la  memoire
  56.     peut etre qualifie d'acces illegal.
  57.  
  58.     L'acces direct illegal en memoire est en  principe  impossible  car
  59.     par  definition  de  l'acces  direct,  seules  les  variables  globales
  60.     peuvent etre accedees ainsi et il est certain que  les  variables  d'un
  61.     programme appartiennent a celui-ci (a part evidement des codes ecrit en
  62.     assembleur    expres    qui  referencent  une  valeur  absolue,  comme    par
  63.     exemple: btst #6,$bfe001; cependant ce code est impossible    a  produire
  64.     en C directement). On peut donc considerer    que  les  acces  direct  en
  65.     memoire ne provoquent pas d'acces illegaux.
  66.  
  67.     En revanche, il est certain que les acces memoire indirects peuvent
  68.     etre illegaux. Il est bien connu qu'un certain nombre de bugs sont  dus
  69.     a des debordements des tableaux. Si le debordement est en lecture, ceci
  70.     n'est pas trop grave; mais si le debordement est en ecriture, cela peut
  71.     provoquer de gros plantages.
  72.  
  73.     Apurify, intervient sur ce genre d'acces en verifiant  la  validite
  74.     des acces memoire par indirection. Apurify garde trace  de    la  memoire
  75.     allouee par le programme et verifie a chaque acces memoire indirect  si
  76.     celui-ci est valide. On peut se dire que cela fait    beaucoup  de  test.
  77.     Certes, oui, mais il faut savoir que Apurify n'est pas fait  pour  etre
  78.     employe en permanence par un programme. Il ne doit servir que dans    une
  79.     phase de mise au point. De plus, il faut remarquer qu'en  realite,  les
  80.     indirections sont tres peu frequentes tout compte fait. En effet, seuls
  81.     les variables liees a des tableaux alloues par malloc() font des  vrais
  82.     acces indirects.  Ainsi,  l'acces  aux  variables  sur  la  pile,  bien
  83.     qu'etant fait par indirection, ne doit pas etre teste puisque ces acces
  84.     sont forcement corrects si la pile    n'est  pas  debordee.  De  meme  en
  85.     modele  SMALL_DATA,  l'acces  aux  variables  globales  se   fait   par
  86.     indirection. Ces indirections ne sont pas non plus a verifier.
  87.  
  88.     Si un acces  indirect  est  detecte  illegal,  APurify    affiche  un
  89.     message d'erreur explicite sur la sortie standard d'erreur du programme
  90.     (admirez la justification complete de la sortie :^). Il y a deux  sorte
  91.     d'acces illegaux. Certains acces se font a de la  memoire  non  detenue
  92.     par le programme (APurify parle alors d'acces entre blocks), alors  que
  93.     d'autre acces se font a cheval sur  un  block  memoire  detenu  par  le
  94.     programme et un autre non  detenu  par  lui  (APurify  parle  alors  de
  95.     debordement de block).
  96.  
  97.     Apurify represente la memoire possedee par le programme sous  forme
  98.     de block. Chaque block est affiche suivant le format
  99.  
  100.                [0x<n1>(<n2>) <attr> (<text>)]
  101.  
  102.     ou <n1> est l'adresse hexadecimale du debut de block, <n2> la  longueur
  103.     decimale du block, <attr> une suite de 3 caracteres de la forme RWS
  104.  
  105.     ou R = block autorise en lecture
  106.        W = block autorise en ecriture
  107.        S = block systeme (= block pre-existant au programme)
  108.  
  109.     si un des acces est interdit,  la  lettre  '-'  remplace  le  caractere
  110.     correspondant, <text> est le nom de  la  procedure    qui  a    allouee  ce
  111.     block. S'il se termine par "*", cela signifie que ce block a ete alloue
  112.     dans une procedure (non analysee par APurify) appelee depuis celle  qui
  113.     est affichee (une fonction en bibliotheque sans doute).
  114.  
  115.     En cas d'erreur, Apurify affiche les blocks entre lesquels  l'acces
  116.     memoire est tombe ou le block deborde ainsi de le  nombre  d'octets  de
  117.     depassement de chaque  block.  Apurify  affiche  aussi  un    block  pour
  118.     representer la memoire accedee. Dans ce block, le debut  du  block    est
  119.     l'adresse memoire fautive, la longueur est la  longeur  de  l'acces  (1
  120.     signifie un acces sur un type char, 2 sur un type short, 4 sur un  type
  121.     int/long et >4 pour un acces par movem illegal). Les attributs  sont  R
  122.     ou W suivant qu'il s'agisse d'un acces en lecture ou  en  ecriture.  Le
  123.     texte, lui, contient le nom  de  la  procedure  dans  laquelle  l'acces
  124.     memoire illegal est intervenu.
  125.  
  126.     APurify detecte aussi la sortie du programme sans  desalloction  de
  127.     certains blocks memoire. (en fait, il detecte les blocks non desalloues
  128.     lors de la fermeture de la librairie).
  129.  
  130.     Certains blocks memoire pre-existant au  programme  sont  reconnus.
  131.     Ceux-ci sont le premier kilo-octet de memoire qui contient les vecteurs
  132.     d'interruption du 680x0, les differents segments  du  programme  et  la
  133.     pile du programme. L'acces a  ces  portions  de  memoire  ne  sera  pas
  134.     declare illegal; de meme que la fermeture de  la  librairie  sans  leur
  135.     desallocations. Ces blocks sont  declares  SYSTEME    (bit  S  sur  leurs
  136.     attributs).
  137.  
  138.     Les blocks alloues par malloc() et autres AllocMem(), ainsi que les
  139.     blocks alloues indirectement (comme ceux alloues  par  OpenScreen()  et
  140.     autres...) sont pris en compte par APurify. Cependant  je  dois  avouer
  141.     que  je  n'ai  pas  encore  teste  les  blocks  alloues  indirectement.
  142.     Cependant, cela doit  marcher  (APurify  patche  les  routines  systeme
  143.     AllocMem() et FreeMem()). Ainsi un programme peut acceder aux bitplanes
  144.     d'un de ses ecrans sans provoquer d'erreur.
  145.  
  146.     Si un acces memoire tombe dans un block memoire mais que l'attribut
  147.     du block est incompatible avec l'acces, APurify affiche une  erreur  de
  148.     protection. Pour l'instant, seul  le  premier  kilo-octet  est  protege
  149.     contre l'ecriture (pour pouvoir lire l'adresse  d'Exec).  Cependant,  a
  150.     l'avenir, il se peut que le block de code  soit  lui-aussi  protege  en
  151.     lecture.
  152.  
  153.     En interne, pour accelerer la recherche de block,  APurify  possede
  154.     un cache des derniers blocks  deja    accedes.  En  effet,  il  est  tres
  155.     probable qu'apres l'acces en memoire a un block, les acces  suivant  se
  156.     feront sur ce block recemment accede. Ainsi,  malgres  la  presence  de
  157.     nombreux blocks memoire, l'execution du  programme  ne  doit  pas  etre
  158.     ralentie de trop. (Cependant, je n'ai  pas  teste  l'efficacite  de  ce
  159.     cache ...).
  160.  
  161. USAGE:
  162. -----
  163.     APurify peut etre vu comme un pre-assembleur. C'est  a  dire  qu'il
  164.     faut  l'utiliser  sur  le  source  assembleur  juste  avant  la   phase
  165.     d'assemblage. Il analyse le  fichier  qui  doit  etre  assemble  et  le
  166.     modifie pour tenir compte de APurify.
  167.  
  168.     Le schema normal d'utilisation a partir d'un code C est de:
  169.  
  170.     - compiler les sources C en generant les codes assembleur.
  171.     - lancer APurify sur chacun de ces sources assembleur.
  172.     - linker tous les .o ensembles avec la librairie APur.
  173.  
  174.     Comme on peut le voir, APurify ne necessite pas de modifier le  code  C
  175.     pour etre utilise. Cependant, il faut ouvrir la librarie par un appel a
  176.     AP_Init() dans le main() et *TRES IMPORTANT* fermer la  bibliotheque  a
  177.     la sortie du programme (juste avant tous les exit())  par  un  appel  a
  178.     AP_Close(). En effet,  etant  donne  qu'APurify  patche  les  fonctions
  179.     AllocMem() et FreeMem() systeme, si le  programme  termine  sans  avoir
  180.     ferme la bibliotheque, le prochain appel a l'une de ces fonctions  fera
  181.     apparaitre le guru....(on vous aura prevenu :-).  Le  plus  simple  est
  182.     d'utiliser la fonction atexit() (par exemple  en  faisant  un  appel  a
  183.     atexit(AP_Close); juste apres l'appel a AP_Init()).
  184.  
  185.     Si on oublie d'ouvrir la bibliotheque dans le programme, un message
  186.     d'avertissement est affiche et l'execution continue sans l'intervention
  187.     d'APurify.
  188.  
  189.     Vous pouvez arreter et redemarrer l'affichage des messages grace  a
  190.     un appel a AP_Report(flag). Si flag est vrai, la  sortie  est  activee.
  191.     S'il est faux, aucun message ne sera  affiche.  C'est  utile  dans  les
  192.     codes d'amorcages. Par exemple, lors de l'utilisation du argv[]  en  C,
  193.     APurify affiche beaucoup de messages errones (les valeurs pointees  par
  194.     argv[] sont considerees comme fausse  puisque  ce  tableau    est  alloue
  195.     avant l'ouverture de la  bibliotheque).  Vous  pouvez  eviter  cela  en
  196.     faisant un AP_Report(0) avant et AP_Report(1) apres le  code  utilisant
  197.     le tableau argv[].
  198.  
  199.     On peut remarquer qu'APurify peut aussi etre utilise sur  tous  les
  200.     langages  generant    un  code  assembleur   intermediaire   (y   compris
  201.     l'assembleur lui meme :-) ). Il faut aussi  noter  qu'il  est  possible
  202.     d'utiliser APurify sur un programme dont on  ne  possede  pas  le  code
  203.     source (ou les .o sans les .asm correspondants).  Il  existe  en  effet
  204.     certains  programmes  permettant  de   generer   un   code     assembleur
  205.     recompilable a partir d'un programme  executable.  A  partir  d'un  tel
  206.     fichier, il suffit de peu de manipulations (ajouter en  debut  de  tous
  207.     les labels le caractere '_'  et  inserer  les  appels  a  AP_Init()  et
  208.     AP_Close() aux bons endroits)  pour pouvoir utiliser APurify.
  209.  
  210.     En principe, APurify introduit l'appel de fonctions  intermediaires
  211.     ainsi que de nouvelle donnees dans le segment de donnees (pour  stocker
  212.     le nom des procedures). La syntaxe d'introduction de nouvelles sections
  213.     ainsi que  de  referencement  a  des  procedures  externes    varie  d'un
  214.     compilateur a l'autre.  APurify  se  debrouille  pour  determiner  quel
  215.     compilateur est utilise en    analysant  le  code.  APurify  connait    les
  216.     pseudo-instructions dseg/dseg, public  (AZTEC)  et  section,  xref/xdef
  217.     (DICE, HCC, ...). Si un compilateur connait  l'une  quelconque  de  ces
  218.     syntaxe, APurify peut etre utilise avec lui (mais  je  n'ai  teste  que
  219.     DICE).
  220.  
  221.     La librairie fournie APur.lib est une librairie  pour  DICE.  Cette
  222.     librairie peut etre utilisee sur  d'autres  compilateurs  acceptant  le
  223.     format de cette librairie (format COMMODORE). Cependant,  DICE  possede
  224.     un symbol specifique pour representer la base de la pile d'un programme
  225.     (variable ULONG *_ExitSP). Si le compilateur choisit pour le linkage ne
  226.     connait pas cette variable, il faut que  vous  declariez  une  variable
  227.     globale identique et pointant sur l'adresse de retour du processus  sur
  228.     la pile (ie:. 8 octets en dessous de la  base  de  la  pile)  moins  44
  229.     octets. C'est a dire que _ExitSP doit valoir:
  230.  
  231.        ULONG *_ExitSP = (ULONG *)((char *)Base_Pile_Processus - 8 - 44).
  232.  
  233.     Pourquoi cette formule barabare ? Eh bien, c'est que la base de la pile
  234.     d'un processus n'est pas toujours celle indiquee  dand  les  champs  du
  235.     systeme. En  fait  chaque  compilateur  possede  une  variable  globale
  236.     pointant sur l'adresse de sortie du processus (celle  qui  est  fournie
  237.     par le systeme sur la pile avant  le  lancement  du  processus).  Cette
  238.     variable doit etre utilisee par la procedure _exit() du C  normalement.
  239.     La base de la pile du processus est  alors    ce  pointeur  +  8  octets.
  240.     Maintenant, a vous d'adapter la valeur de _ExitSP en fonction de  votre
  241.     compilateur.
  242.  
  243.     Si la libraire n'est pas bonne, vous pouvez la  reconstruire.  Pour
  244.     cela, compilez APfuncs.c et APserv.a (modifiez-les a votre gout).  Puis
  245.     fusionnez-les ensembles pour creer APur.lib.
  246.  
  247. PARTIE LEGALE:
  248. -------------
  249.     Ce programme  est  livre  tel  quel.  Je  ne  dois  pas  etre  tenu
  250.     responsable pour les mefaits entraines pas l'utilisation de ce logiciel
  251.     (en revanche, je veux bien etre tenu  responsable  pour  les  bienfaits
  252.     engendres par ce logiciel :^). Employez  ce  programme  a  vos  propres
  253.     risques.
  254.  
  255.     Ce programme est freeware. Vous pouvez l'utiliser et le  distribuer
  256.     librement a condition de garder l'archive intacte (pas d'alteration des
  257.     fichiers sauf eventuelle compression). Il ne peut etre vendu a mon insu
  258.     (bien qu'une  somme  modique  puisse  etre  demandee  pour  le  support
  259.     materiel (diskette, CD,...) dans la  cas  de  distribution  organisee).
  260.     Toute utilisation commerciale  de  ce  logiciel  et  toute    vente  avec
  261.     plus-value doit  m'etre  demandee  par  avance.  Je  garde  les  droits
  262.     d'auteurs sur ce programme ainsi que sur ses futures  versions.  Je  me
  263.     reserve  le  droit    de  modifier  ce  programme  sans  en  avertir    les
  264.     utilisateurs.
  265.  
  266.     Je veux bien que chaque utilisateur de    ce  logiciel  m'envoie  une
  267.     carte postale en echange son l'utilisation ou tout autre chose (argent,
  268.     documentation, amiga, ...). Mais ceci n'est pas une obligation :-). Mon
  269.     adresse postale est:
  270.  
  271.         M. DEVULDER Samuel
  272.         1, Rue du chateau
  273.         59380 STEENE
  274.         FRANCE
  275.  
  276.     Vous pouvez m'envoyer des suggestions,  les  bugs  decouverts  dans  le
  277.     logiciel a mon adresse electronique suivante:
  278.  
  279.         devulder@info.unicaen.fr
  280.  
  281. DISTRIBUTION:
  282. ------------
  283.         Cette distribution contient les versions francaise et  anglaise
  284.     de ce logiciel:
  285.  
  286.     - doc/APurify.doc:     Documention anglaise
  287.     - doc/APurify.doc.fre: Cette documentation francaise
  288.  
  289.      _/ - bin/APurify.fre:     Version francaise de l'analyseur
  290.     | \ - bin/APurify:           Version anglaise de l'analyseur
  291.     |
  292.     +-----> a renomer en APurify suivant votre choix.
  293.  
  294.      _/ - lib/APur.lib.fre:    Version francaise de la librairie
  295.     | \ - lib/APur.lib:        Version anglaise de la librairie
  296.     |
  297.     +-----> a renomer en APur.lib suivant votre choix. Cette librairie    est
  298.         au format COMMODORE (generee par DICE).
  299.  
  300.      _/ - lib/APfuncs.c
  301.     | \ - lib/APserv.a
  302.     |
  303.     +-----> pour reconstruire la librairie.
  304.  
  305.     - test/test.c:           Source d'un programme de test debile
  306.     - test/test.fre:       Programme de test linke avec APur.lib.fre
  307.     - test/test:           Programme de test linke avec APur.lib.
  308.  
  309.  
  310. NOTES:
  311. -----
  312.     Ma configuration est la suivante: un viel A500 1Mo RAM de  1989,  1
  313.     lecteur de diskette, KS1.3, et beaucoup de patience (ah si  j'avais  un
  314.     A4000/68040/33Mhz !).
  315.  
  316.     L'idee de ce programme m'a ete donnee  apres  une  discussion  avec
  317.     Cedric BEUST (AMIGA NEWS) sur IRC (Internet Relay Chat). Merci Cedric !
  318.  
  319.     Toutes les marques citees sont proprietes  de  leurs  proprietaires
  320.     respectifs.
  321.  
  322.     APurify a ete compile avec netdcc, la version  non  enregistree  de
  323.     DICE, par Matt DILLON.
  324.  
  325.     Le source du scanneur de source assembleur a ete bati a  partir  de
  326.     l'optimisateur TOP de  la  distribution  HCC  ((c)  Sozobon  ltd,  Tony
  327.     Andrews & Detlef Wuerkner).
  328.  
  329.     Il existe un certain nombre de programme realisant a  peu  pres  la
  330.     meme chose que APurify. Par exemple, FORTIFY de Simon P.  Bullen,  mais
  331.     il ne detecte que les acces en ecriture  illegaux  sur  les  bords    des
  332.     blocks alloues lors de la  liberation  des    ces  blocks.  Ainsi  il  ne
  333.     detecte pas les debordements trop important ainsi que les  debordements
  334.     en lecture et la detection n'est pas  immediate.  Enforcer  peut  aussi
  335.     detecter les acces illegaux de la memoire, il me semble, mais  il  fait
  336.     usage d'extensions materielles (MMU).
  337.  
  338. BUGS:
  339. ----
  340.     APurify ne  connait  pas  la  memoire  publique  dans  laquelle  un
  341.     programme peut lire ou ecrire sans l'avoir alloue. Ainsi, il  reportera
  342.     une erreur quand un programme accede au contenu d'un message obtenu par
  343.     un GetMsg().
  344.  
  345.     APurify ne sait analyser que le code 68000. Si le  source  contient
  346.     des instructions 680x0 (x>1), et si ces instructions sont inconnues  du
  347.     68000 (ex: les instructions de champ de  bits),  elles  ne  seront  pas
  348.     traitee. Si c'est un mode d'adressage inconnu, il reportera un  message
  349.     d'erreur. Cependant, ceci peut etre corrige  des  que  j'aurais  eu  le
  350.     source d'un assembleur 680x0 (x>1) {mais il faut le  temps...  et  vous
  351.     etes bienvenus de me dire si vous en possedez un}.
  352.  
  353.     Il se peut que APurify affiche de faux messages selon  lesquels  la
  354.     bibliotheque est fermee sans avoir liberee des blocks de memoire.  Cela
  355.     est du au fait que printf()  alloue  de  la  memoire  qui  est  liberee
  356.     seulement a la sortie du programme. Je n'y peut rien, mais vous  pouvez
  357.     faire un AP_Report(0) avant la sortie  du  programme  pour  eviter  les
  358.     affichages. Neanmoins, il est  preferable  de  detecter  de  faux  bugs
  359.     plutot que d'en louper quelques uns !
  360.  
  361.     Sans doute d'autres bugs... j'attend vos rapports.
  362.  
  363.